package com.ogawa.projectcommon.network

import android.util.Log
import com.blankj.utilcode.util.LogUtils
import com.ogawa.base.constants.Constants
import com.ogawa.projectcommon.network.Sign
import com.ogawa.base.utils.SpUtil
import com.ogawa.projectcommon.utils.ProjectSpUtils
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import okio.Buffer
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.EOFException
import java.lang.Exception
import java.nio.charset.Charset
import java.util.*
import java.util.concurrent.TimeUnit

open class RetrofitManager {
    private var retrofit: Retrofit

    companion object {
        val INSTANCE: RetrofitManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            RetrofitManager()
        }
        private const val TAG = "RetrofitManager"
        private const val DEFAULT_TIMEOUT = 30.toLong() // 超时时间
    }

    private constructor() {
        val logInterceptor = HttpLoggingInterceptor(
            HttpLoggingInterceptor.Logger { message ->
                Log.e(
                    TAG,
                    "HttpLoggingInterceptor --- message =$message"
                )
            }
        ).setLevel(HttpLoggingInterceptor.Level.BODY)
        var interceptor = Interceptor { chain ->
            val appId = Constants.APP_ID
            val timeStamp = System.currentTimeMillis().toString()
            val requestId = UUID.randomUUID().toString()
            var builder = StringBuilder()
            var request = chain.request()
            val method = request.method().toLowerCase();// 请求方式
            val url = request.url().toString().substring(Constants.API_SERVICE.length)
            var jsonBody = ""
            val body = request.body()
            if (body != null) {
                val buffer = Buffer()
                body.writeTo(buffer)
                var charset = Charset.forName("UTF-8")
                val contentType = body.contentType()
                if (contentType != null) {
                    charset = contentType.charset(charset)
                }
                if (isPlaintext(buffer) && charset != null) {
                    jsonBody = buffer.readString(charset)
                }
            }
            builder.append(method)
                .append("\n")
                .append(url)
                .append("\n")
                .append(appId)
                .append("\n")
                .append(timeStamp)
                .append("\n")
                .append(requestId)
                .append("\n")
                .append(jsonBody)
            if(jsonBody.length < 2048){
                LogUtils.e("request json:$jsonBody")
            }

            val signature =
                Sign.signature(Constants.RSA_PRIVATE, builder.toString()) // 签名
            var userToken = ""
            try{
                userToken = ProjectSpUtils.getUserInfo().token
            }catch (e:Exception){

            }
            val language = SpUtil.get(SpUtil.LANGUAGE, Constants.ZH) as String
            request = request.newBuilder()
                .addHeader("Content-Type", "application/json")
                .addHeader("Authorization", appId)
                .addHeader("x-timestamp", timeStamp)
                .addHeader("x-request-id", requestId)
                .addHeader("x-signature", signature)
                .addHeader("x-token", userToken)
                .addHeader("x-locale", language)
//                .addHeader("x-devmode", "1")
                .build()
            val proceed = chain.proceed(request)
            return@Interceptor proceed
        }

        val okHttp = OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .addInterceptor(logInterceptor)
            .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
            .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
            .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
            .build()
        retrofit = Retrofit.Builder()
            .baseUrl(Constants.API_SERVICE)
            .client(okHttp)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

    private fun isPlaintext(buffer: Buffer): Boolean {
        return try {
            val prefix = Buffer()
            val byteCount = if (buffer.size < 64) buffer.size else 64
            buffer.copyTo(prefix, 0, byteCount)
            for (i in 0..15) {
                if (prefix.exhausted()) {
                    break
                }
                val codePoint = prefix.readUtf8CodePoint()
                if (Character.isISOControl(codePoint) && !Character.isWhitespace(
                        codePoint
                    )
                ) {
                    return false
                }
            }
            true
        } catch (e: EOFException) {
            false // Truncated UTF-8 sequence.
        }
    }


    /**
     * 创建相应的接口代理
     *
     * @param service
     * @param <V>
     * @return
    </V> */
    open fun <V> createService(service: Class<V>): V {
        return retrofit.create(service)
    }
}